<?php

namespace StudyBuddy\Modules\Tumblr;

use \StudyBuddy\Interfaces\TumblrUser;
use \StudyBuddy\StudyBuddyObject;
use \StudyBuddy\Registry;

/**
 * Main class for Writing (posting) to Tumblr OAuth API
 *
 */
class ApiClient extends StudyBuddyObject {
    const API_WRITE_URL = 'http://www.tumblr.com/api/write';

    /**
     *
     * OAuth
     * @var object of type OAuth
     */
    protected $oAuth;

    /**
     * TumblrUser
     *
     * @var Object of type TumblrUser
     * set ONLY if User has Tumblr Oauth credentials
     */
    protected $oUser;

    /**
     * Tumblr API Config array
     * This is an array of TUMBLR section from !config.ini
     *
     * @var array
     */
    protected $aConfig;

    /**
     * Constructory
     * 
     * @param Registry $oRegistry
     * @throws \StudyBuddy\Exception
     * @throws \StudyBuddy\DevException
     * @throws \StudyBuddy\Exception 
     */
    public function __construct(Registry $oRegistry) {
        if (!extension_loaded('oauth')) {
            throw new \StudyBuddy\Exception('Cannot use this class because php extension "oauth" is not loaded');
        }

        $this->oRegistry = $oRegistry;
        $this->aConfig = $oRegistry->Ini->offsetGet('TUMBLR');
        d('$this->aConfig: ' . print_r($this->aConfig, 1));
        if (empty($this->aConfig) || empty($this->aConfig['OAUTH_KEY']) || empty($this->aConfig['OAUTH_SECRET'])) {
            throw new DevException('Missing configuration parameters for TUMBLR API');
        }

        $this->setUser($oRegistry->Viewer);

        try {
            d('cp');
            $this->oAuth = new \OAuth($this->aConfig['OAUTH_KEY'], $this->aConfig['OAUTH_SECRET'], OAUTH_SIG_METHOD_HMACSHA1, OAUTH_AUTH_TYPE_URI);
            $this->oAuth->enableDebug();

            d('cp');
        } catch (\OAuthException $e) {
            e('OAuthException: ' . $e->getMessage() . ' ' . print_r($e, 1));

            throw new Exception('Something went wrong during Tumblr authorization. This has nothing to do with your account. Please try again later' . $e->getMessage());
        }
    }

    /**
     * Set $this->oUser but only
     * of $oUser has tumblr oauth token
     *
     * @param TumblrUser $oUser
     */
    public function setUser(TumblrUser $oUser) {
        if (null !== $oUser->getTumblrToken()) {
            $this->oUser = $oUser;
        } else {
            d('user does not have Tumblr oauth token');

            return false;
        }

        return $this;
    }

    /**
     * Getter for $this->oUser
     *
     * @return object $this->oUser
     */
    public function getUser() {
        return $this->oUser;
    }

    /**
     * Add content to Tumblr
     * @todo finish this to handle posting
     * of link, photo, autio, video
     *
     * @param TumblrContent $post
     */
    public function add(TumblrContent $post) {
        if ($post instanceof TumblrPost) {
            return $this->addBlogPost($post);
        }
    }

    /**
     * @todo unfihished
     *
     * @param TumblrContent $post
     */
    public function edit(TumblrContent $post) {
        
    }

    /**
     * @todo unfihished
     *
     * @param TumblrContent $post
     */
    public function delete(TumblrContent $post) {
        
    }

    /**
     * @todo Add 'state' set to o->getState()
     * @todo add 'private' set to o->getPrivate()
     *
     * @param TumblrPost $o
     */
    protected function addBlogPost(TumblrPost $o) {
        $data = array(
            'title' => $o->getTitle(),
            'body' => $o->getBody(),
            'generator' => $o->getGenerator()
        );

        if ('' !== $slug = $o->getSlug()) {
            $data['slug'] = $slug;
        }

        if ('' !== $tags = $o->getTags()) {
            $data['tags'] = $tags;
        }

        d('data: ' . print_r($data, 1));

        return $this->apiWrite($data);
    }

    /**
     * @todo unfihished
     *
     * @param TumblrImage $o
     */
    protected function addImage(TumblrImage $o) {
        
    }

    /**
     * @todo unfihished
     *
     * @param TumblrLink $o
     */
    protected function addLink(TumblrLink $o) {
        
    }

    /**
     * Post data to Tumblr API
     *
     * @param array $data
     * @throws \LogicException
     * @throws \StudyBuddy\Exception
     *
     * @return string whatever is retunred by Tumblr Api
     * in case of adding blog post it is id of new post
     */
    protected function apiWrite(array $data) {
        if (!isset($this->oUser)) {
            throw new \LogicException('Cannot use API because $this->oUser not set');
        }

        $data['group'] = $this->oUser->getTumblrBlogId();

        try {

            $this->oAuth->setAuthType(OAUTH_AUTH_TYPE_FORM);
            $token = $this->oUser->getTumblrToken();
            $secret = $this->oUser->getTumblrSecret();

            d('setting $token: ' . $token . ' secret: ' . $secret);

            $this->oAuth->setToken($token, $secret);
            d('fetching: ' . self::API_WRITE_URL . ' data: ' . print_r($data, 1));
            $this->oAuth->fetch(self::API_WRITE_URL, $data);
        } catch (\OAuthException $e) {
            $aDebug = $this->oAuth->getLastResponseInfo();
            d('debug: ' . print_r($aDebug, 1));

            e('OAuthException: ' . $e->getMessage());
            /**
             * Should NOT throw Exception because
             * we are not sure it was actually due to authorization
             * or maby Tumblr was bugged down or something else
             */
            throw new \StudyBuddy\Exception('Something went wrong during connection with Tumblr. Please try again later' . $e->getMessage());
        }

        return $this->getResponse();
    }

    /**
     *
     * Extract response from Oauth, examine
     * the http response code
     * In case of 401 code - revoke user's Tumblr Oauth credentials
     * @throws \StudyBuddy\DevException
     */
    protected function getResponse() {
        $ret = $this->oAuth->getLastResponse();

        $aDebug = $this->oAuth->getLastResponseInfo();
        d('debug: ' . print_r($aDebug, 1));
        if ('200' == $aDebug['http_code'] || '201' == $aDebug['http_code']) {
            d('successful post to API');

            return $ret;
        } elseif ('401' == $aDebug['http_code']) {
            d('Tumblr oauth failed with 401 http code. Data: ' . print_r($aData, 1));
            /**
             * If this method was passed oUser
             * then null the tokens
             * and save the data to table
             * so that next time we will know
             * that this User does not have tokens
             */
            if (is_object($this->oUser)) {
                d('Going to revoke access tokens for user object');
                $this->oUser->revokeTumblrToken();
                /**
                 * Important to post this update
                 * so that user object will be removed from cache
                 */
                $this->oRegistry->Dispatcher->post($this->oUser, 'onTumblrTokenUpdate');
            }

            /**
             * This exception should be caught all the way in WebPage and it will
             * cause the ajax message with special key=>value which will
             * trigger the popup to be shown to user with link
             * to signing with Tumblr
             */
            throw new \StudyBuddy\DevException('Tumblr API OAuth credentials failed. Possibly user removed our app');
        } else {
            e('Tumblr API Post failed http code was: ' . $aDebug['http_code'] . ' full debug: ' . print_r($aDebug, 1) . ' response: ' . $ret);

            throw new \StudyBuddy\DevException('Tumblr OAuth post failed');
        }
    }

}
